package org.jrazdacha.bittorrent.modelling.agent;

import jade.core.Agent;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.SearchConstraints;
import jade.domain.FIPAAgentManagement.ServiceDescription;

import java.util.HashSet;
import java.util.Set;

import org.jrazdacha.bittorrent.modelling.core.Id;

/**
 * Provides useful methods for interaction with Directory Facilitator Agent
 * 
 * @author nep
 *
 */
public class DFUtils {
	private static final Long WITHOUT_LIMITATION = new Long(-1);
	private static final String BITTORRENT_SERVICE = "bittorrent";
	private static final DFAgentDescription agentDescription;
	private static final SearchConstraints all;
	
	static {
		agentDescription = bittorrentAgentDescription();	
		all = new SearchConstraints();
		all.setMaxResults(WITHOUT_LIMITATION);
	}
	
	/**
	 * Performs registering agent in Directory Facilitator agent(Bittorent Tracker)
	 * 
	 * @param agent to register
	 */
	public static void registerAgent(Agent agent) {
		DFAgentDescription dfd = bittorrentAgentDescription(agent.getLocalName());		
		dfd.setName(agent.getAID());	    	    
	    try {
			DFService.register(agent, dfd);
		} catch (FIPAException e) {
			throw new RuntimeException(e);
		}
	}	
	
	/**
	 * Deletes record about given agent from Directory Facilitator Agent
	 * 
	 * @param agent
	 */
	public static void deregisterAgent(Agent agent) {
		try {
			DFService.deregister(agent);
		}
		catch (FIPAException e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * Asks from Directory Facilirator(bittorrent tracker) other agents(peers)
	 * 
	 * @param agent agent which asks other peers
	 * @return other agents(peers) from Directory Facilitator(tracker) 
	 */
	public static Set<Id> askPeers(Agent agent) {									
		try {
			return findAgentsFor(agent);
		}
		catch(FIPAException fe) {
			throw new RuntimeException(fe);			
		}			
	}
	
	private static Set<Id> findAgentsFor(Agent agent) throws FIPAException {
		Set<Id> result = new HashSet<Id>();
		DFAgentDescription[] searchResult = DFService.search(agent, agentDescription, all);			
		for (DFAgentDescription dfAgentDescription : searchResult) {
			 result.add(new IdAIDImpl(dfAgentDescription.getName()));
		}
		return result;
	}
	
	private static DFAgentDescription bittorrentAgentDescription(String agentLocalName) {
		DFAgentDescription result = new DFAgentDescription();
		ServiceDescription sd = new ServiceDescription();
		sd.setType(BITTORRENT_SERVICE);
		if (null != agentLocalName) {
			sd.setName(agentLocalName);
		}
		result.addServices(sd);
		return result;
	}
	
	private static DFAgentDescription bittorrentAgentDescription() {
		return bittorrentAgentDescription(null);
	}
}
